package com.book.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.book.mapper.OrderMapper;
import com.book.ordermanagement.command.OrderCommand;
import com.book.ordermanagement.state.OrderStateChangeAction;
import com.book.pojo.Order;
import com.book.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static com.book.ordermanagement.state.OrderStateConstant.ORDER_WAIT_PAY;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    // 注入状态机
    private final StateMachine<String, OrderStateChangeAction> orderStateMachine;

    // 注入RedisPersister存储工具

    private final StateMachinePersister<String, OrderStateChangeAction, String> stateMachineRedisPersister;
    // 注入redis
    private final  StringRedisTemplate redisTemplate;

private final OrderCommand orderCommand;



    @Override
    public Order createOrder(String productId) {
        String orderId = "OID" + productId;
        Order order = new Order()
                .setOrderId(orderId)
                .setProductId(productId)
                .setOrderState( ORDER_WAIT_PAY);
        redisTemplate.opsForValue().set(orderId, JSON.toJSONString(order),900, TimeUnit.SECONDS);

        orderCommand.execute(order);// 这里也可以像listener 中那么写，使用具体执行者 来调用命令
        return order;
    }

    //订单支付
    @Override

    public Order pay(String orderId) {
        //从Redis中获取 订单
        String orderStr = redisTemplate.opsForValue().get(orderId);
        if (StringUtils.isBlank(orderStr)) {
            throw new RuntimeException("订单不存在");
        }
        Order order = JSON.parseObject(orderStr,Order.class);
        //包装 订单状态变更 Message，并附带订单操作 PAY_ORDER
        Message message = MessageBuilder
                .withPayload(OrderStateChangeAction.PAY_ORDER)
                .setHeader("order", order).build();
        //将Message传递给Spring状态机

        if(changeStateAction(message,order)) {
            return order;
        }
        return null;
    }
    //订单发送
    @Override

    public Order send(String orderId) {
        //从Redis中获取 订单
        String orderStr = redisTemplate.opsForValue().get(orderId);
        if (StringUtils.isBlank(orderStr)) {
            throw new RuntimeException("订单不存在");
        }
        Order order = JSON.parseObject(orderStr,Order.class);
        //包装 订单状态变更 Message，并附带订单操作 SEND_ORDER
        Message message = MessageBuilder
                .withPayload(OrderStateChangeAction.SEND_ORDER).setHeader("order", order).build();
        //将Message传递给Spring状态机
        if(changeStateAction(message,order)) {
            return order;
        }
        return null;
    }
    //订单签收
    @Override

    public Order receive(String orderId) {
        //从Redis中获取 订单
        String orderStr = redisTemplate.opsForValue().get(orderId);
        if (StringUtils.isBlank(orderStr)) {
            throw new RuntimeException("订单不存在");
        }
        Order order = JSON.parseObject(orderStr,Order.class);
        //包装 订单状态变更 Message，并附带订单操作 RECEIVE_ORDER
        Message message = MessageBuilder
                .withPayload(OrderStateChangeAction.RECEIVE_ORDER).setHeader("order", order).build();
        //将Message传递给Spring状态机
        if(changeStateAction(message,order)) {
            return order;
        }
        return null;
    }
    //状态机的相关操作
    private boolean changeStateAction(Message<OrderStateChangeAction> message, Order order) {
        try {
            //启动状态机
            orderStateMachine.start();
            //从Redis缓存中读取状态机，缓存的Key为orderId+"STATE"，这是自定义的，读者可以根据自己喜好定义
            stateMachineRedisPersister.restore(orderStateMachine, order.getOrderId()+"STATE");
            //将Message发送给OrderStateListener
            boolean res = orderStateMachine.sendEvent(message);
            //将更改完订单状态的 状态机 存储到 Redis缓存
            stateMachineRedisPersister.persist(orderStateMachine, order.getOrderId()+"STATE");
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            orderStateMachine.stop();
        }
        return false;
    }


}